﻿using System;
using System.Collections.Generic;
using System.Text;
using PostSharp.Aspects.Dependencies;

namespace Arcana.Contract.Method.Returns.Is.Not.In
{
    /// <summary>
    /// Represents a contract that adheres to <b>Method returns a value that is not in the specified range.</b>
    /// </summary>
    [Serializable]
    [ProvideAspectRole(Roles.Contract)]
    [ProvideAspectRole(Roles.Method)]
    [ProvideAspectRole(Roles.ReturnValue)]
    [ProvideAspectRole(Roles.Conditional)]
    [AspectRoleDependency(AspectDependencyAction.Commute, Roles.Conditional)]
    public sealed class RangeAttribute : ComparingContractBase
    {
        private object _minValue;
        private object _maxValue;

        /// <summary>
        /// Initializes a new instance of <b>Method.Returns.Is.Not.In.RangeAttribute</b>.
        /// </summary>
        /// <param name="minValue">The minimum value of the prohibited range.</param>
        /// <param name="maxValue">The maximum value of the prohibited range.</param>
        /// <exception cref="System.ArgumentNullException"><i>minValue</i> or <i>maxValue</i> are <b>null</b>.</exception>
        /// <exception cref="System.ArgumentException"><i>minValue</i> is greater than <i>maxValue</i>.</exception>
        public RangeAttribute(object minValue, object maxValue)
        {
            if (minValue == null || maxValue == null) throw new ArgumentNullException();
            if (Comparer.Compare(minValue, maxValue) > 0) throw new ArgumentException();
            _minValue = minValue;
            _maxValue = maxValue;
        }

        /// <summary>
        /// Performs validation on the retunr value.
        /// </summary>
        /// <param name="value">The return value that should be validated.</param>
        /// <returns><b>true</b> if <i>value</i> is validated, otherwise <b>false</b>.</returns>
        protected override bool ValidateValue(object value)
        {
            return Comparer.Compare(value, _minValue) < 0 || Comparer.Compare(value, _maxValue) > 0;
        }
    }
}
